package com.example.mqmanager.service;

import com.example.mqmanager.config.DynamicRedisConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

@Service
public class RedisManagerService {

    @Autowired
    private DynamicRedisConfig dynamicRedisConfig;

    /**
     * 获取所有键
     *
     * @param pattern 匹配模式
     * @return 键集合
     */
    public Set<String> getKeys(String pattern) {
        return getKeys(pattern, dynamicRedisConfig.getHost(), dynamicRedisConfig.getPort(),
                dynamicRedisConfig.getPassword(), dynamicRedisConfig.getDatabase());
    }

    /**
     * 获取所有键（指定连接信息）
     *
     * @param pattern 匹配模式
     * @param host Redis主机
     * @param port Redis端口
     * @param password Redis密码
     * @param database Redis数据库
     * @return 键集合
     */
    public Set<String> getKeys(String pattern, String host, int port, String password, int database) {
        RedisConnectionFactory connectionFactory = dynamicRedisConfig.getConnectionFactory(host, port, password, database);
        StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
        
        // 初始化连接工厂
        connectionFactory.getConnection();
        
        try {
            if (pattern == null || pattern.isEmpty()) {
                pattern = "*";
            }
            return redisTemplate.keys(pattern);
        } catch (Exception e) {
            throw new RuntimeException("获取Redis键时出错: " + e.getMessage(), e);
        } finally {
            // 关闭连接
            try {
                if (connectionFactory != null) {
                    connectionFactory.getConnection().close();
                }
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }

    /**
     * 获取键的值
     *
     * @param key 键
     * @return 值
     */
    public Object getValue(String key) {
        return getValue(key, dynamicRedisConfig.getHost(), dynamicRedisConfig.getPort(),
                dynamicRedisConfig.getPassword(), dynamicRedisConfig.getDatabase());
    }

    /**
     * 获取键的值（指定连接信息）
     *
     * @param key 键
     * @param host Redis主机
     * @param port Redis端口
     * @param password Redis密码
     * @param database Redis数据库
     * @return 值
     */
    public Object getValue(String key, String host, int port, String password, int database) {
        RedisConnectionFactory connectionFactory = dynamicRedisConfig.getConnectionFactory(host, port, password, database);
        StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
        
        // 初始化连接工厂
        connectionFactory.getConnection();
        
        try {
            String type = redisTemplate.type(key).code();
            switch (type) {
                case "string":
                    return redisTemplate.opsForValue().get(key);
                case "list":
                    return redisTemplate.opsForList().range(key, 0, -1);
                case "set":
                    return redisTemplate.opsForSet().members(key);
                case "zset":
                    return redisTemplate.opsForZSet().rangeWithScores(key, 0, -1);
                case "hash":
                    return redisTemplate.opsForHash().entries(key);
                default:
                    return "Unsupported type: " + type;
            }
        } catch (Exception e) {
            throw new RuntimeException("获取Redis键值时出错: " + e.getMessage(), e);
        } finally {
            // 关闭连接
            try {
                if (connectionFactory != null) {
                    connectionFactory.getConnection().close();
                }
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }

    /**
     * 获取键的值和有效期
     *
     * @param key 键
     * @return 包含值和有效期的Map
     */
    public Map<String, Object> getValueAndTTL(String key) {
        return getValueAndTTL(key, dynamicRedisConfig.getHost(), dynamicRedisConfig.getPort(),
                dynamicRedisConfig.getPassword(), dynamicRedisConfig.getDatabase());
    }

    /**
     * 获取键的值和有效期（指定连接信息）
     *
     * @param key 键
     * @param host Redis主机
     * @param port Redis端口
     * @param password Redis密码
     * @param database Redis数据库
     * @return 包含值和有效期的Map
     */
    public Map<String, Object> getValueAndTTL(String key, String host, int port, String password, int database) {
        RedisConnectionFactory connectionFactory = dynamicRedisConfig.getConnectionFactory(host, port, password, database);
        StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
        
        // 初始化连接工厂
        connectionFactory.getConnection();
        
        try {
            Map<String, Object> result = new HashMap<>();
            
            // 获取过期时间(-1表示永不过期，-2表示键不存在)
            Long ttl = redisTemplate.getExpire(key);
            result.put("ttl", ttl);
            
            // 获取键的类型
            String type = redisTemplate.type(key).code();
            result.put("type", type);
            
            // 根据不同类型获取值
            switch (type) {
                case "string":
                    result.put("value", redisTemplate.opsForValue().get(key));
                    break;
                case "list":
                    result.put("value", redisTemplate.opsForList().range(key, 0, -1));
                    break;
                case "set":
                    result.put("value", redisTemplate.opsForSet().members(key));
                    break;
                case "zset":
                    result.put("value", redisTemplate.opsForZSet().rangeWithScores(key, 0, -1));
                    break;
                case "hash":
                    result.put("value", redisTemplate.opsForHash().entries(key));
                    break;
                default:
                    result.put("value", "Unsupported type: " + type);
            }
            
            return result;
        } catch (Exception e) {
            throw new RuntimeException("获取Redis键值和有效期时出错: " + e.getMessage(), e);
        } finally {
            // 关闭连接
            try {
                if (connectionFactory != null) {
                    connectionFactory.getConnection().close();
                }
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }

    /**
     * 删除键
     *
     * @param key 键
     * @return 是否删除成功
     */
    public boolean deleteKey(String key) {
        return deleteKey(key, dynamicRedisConfig.getHost(), dynamicRedisConfig.getPort(),
                dynamicRedisConfig.getPassword(), dynamicRedisConfig.getDatabase());
    }

    /**
     * 删除键（指定连接信息）
     *
     * @param key 键
     * @param host Redis主机
     * @param port Redis端口
     * @param password Redis密码
     * @param database Redis数据库
     * @return 是否删除成功
     */
    public boolean deleteKey(String key, String host, int port, String password, int database) {
        RedisConnectionFactory connectionFactory = dynamicRedisConfig.getConnectionFactory(host, port, password, database);
        StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
        
        // 初始化连接工厂
        connectionFactory.getConnection();
        
        try {
            return redisTemplate.delete(key);
        } catch (Exception e) {
            throw new RuntimeException("删除Redis键时出错: " + e.getMessage(), e);
        } finally {
            // 关闭连接
            try {
                if (connectionFactory != null) {
                    connectionFactory.getConnection().close();
                }
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }

    /**
     * 批量删除键
     *
     * @param keys 键集合
     * @return 删除的键数量
     */
    public long deleteKeys(Set<String> keys) {
        return deleteKeys(keys, dynamicRedisConfig.getHost(), dynamicRedisConfig.getPort(),
                dynamicRedisConfig.getPassword(), dynamicRedisConfig.getDatabase());
    }

    /**
     * 批量删除键（指定连接信息）
     *
     * @param keys 键集合
     * @param host Redis主机
     * @param port Redis端口
     * @param password Redis密码
     * @param database Redis数据库
     * @return 删除的键数量
     */
    public long deleteKeys(Set<String> keys, String host, int port, String password, int database) {
        RedisConnectionFactory connectionFactory = dynamicRedisConfig.getConnectionFactory(host, port, password, database);
        StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
        
        // 初始化连接工厂
        connectionFactory.getConnection();
        
        try {
            return redisTemplate.delete(keys);
        } catch (Exception e) {
            throw new RuntimeException("批量删除Redis键时出错: " + e.getMessage(), e);
        } finally {
            // 关闭连接
            try {
                if (connectionFactory != null) {
                    connectionFactory.getConnection().close();
                }
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }

    /**
     * 更新Redis配置
     */
    public void updateRedisConfig(String host, int port, String password, int database) {
        dynamicRedisConfig.setHost(host);
        dynamicRedisConfig.setPort(port);
        dynamicRedisConfig.setPassword(password);
        dynamicRedisConfig.setDatabase(database);
    }

    /**
     * 设置键值对
     *
     * @param key 键
     * @param value 值
     * @return 是否设置成功
     */
    public boolean setValue(String key, String value) {
        return setValue(key, value, dynamicRedisConfig.getHost(), dynamicRedisConfig.getPort(),
                dynamicRedisConfig.getPassword(), dynamicRedisConfig.getDatabase());
    }

    /**
     * 设置键值对（指定连接信息）
     *
     * @param key 键
     * @param value 值
     * @param host Redis主机
     * @param port Redis端口
     * @param password Redis密码
     * @param database Redis数据库
     * @return 是否设置成功
     */
    public boolean setValue(String key, String value, String host, int port, String password, int database) {
        RedisConnectionFactory connectionFactory = dynamicRedisConfig.getConnectionFactory(host, port, password, database);
        StringRedisTemplate redisTemplate = new StringRedisTemplate(connectionFactory);
        
        // 初始化连接工厂
        connectionFactory.getConnection();
        
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            throw new RuntimeException("设置Redis键值时出错: " + e.getMessage(), e);
        } finally {
            // 关闭连接
            try {
                if (connectionFactory != null) {
                    connectionFactory.getConnection().close();
                }
            } catch (Exception e) {
                // 忽略关闭异常
            }
        }
    }
}